## @package sentry2.py
# This module implements the logic and control to be used by the
# SENTRY-2 model from within the Blender Game Engine (BGE).
#
# More details.
#
# -----------------------------------------------------------------------------
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# -----------------------------------------------------------------------------


# -----[ Imports ]-------------------------------------------------------------
import bge
import aud
import mathutils
import time
#import mathutils as Mathutils
#from mathutils import * 


# -----[ Local Variables ]-----------------------------------------------------
controller = bge.logic.getCurrentController()                                           # Current logic controller.
bot = controller.owner                                                                  # Current bot physics object.
scene = bge.logic.getCurrentScene()                                                     # Current scene.
keyboard = bge.logic.keyboard                                                           # Current keyboard.
armature = [child for child in bot.childrenRecursive if "Armature" in child.name][0]    # Current bot armature.


# -----[ Local Functions ]-----------------------------------------------------


## Documentation for a function.
#
# More details.
def initialize():
    global bot

    # Verify that we have not been initialized already.
    if "prv_IsInitialized" in bot:
        return # We have already been initialized.

    # Flag that we've been initialized.
    bot["prv_IsInitialized"] = True

    # Create and initialize our internal control variables (safely).
    if not "prv_Stealth" in bot:
        bot["prv_Stealth"] = True
    if not "prv_ProjectileToggle" in bot:
        bot["prv_ProjectileToggle"] = False
    if not "prv_Counter" in bot:
        bot["prv_Counter"] = 0

    # Our user supplied settings are not required to be supplied by
    # the end user.  If they have not supplied settings, create and
    # initialize them to defaults.
    if not "pub_DeployRate" in bot:
        bot["pub_DeployRate"] = 1.0
    if not "pub_RangeDetect" in bot:
        bot["pub_RangeDetect"] = 40
    if not "pub_RangeFire" in bot:
        bot["pub_RangeFire"] = 20
    if not "pub_ProjectileRate" in bot:
        bot["pub_ProjectileRate"] = 1000
    if not "pub_ProjectileObject" in bot:
        bot["pub_ProjectileObject"] = "Sentry2_Bullet"
    if not "pub_ProjectileAlternate" in bot:
        bot["pub_ProjectileAlternate"] = False

    # Create and initialize our sound assets.
    bge.logic.device = aud.device()
    soundpath = bge.logic.expandPath("//slimeball.wav")
    bot["snd_fire_primary_1"] = aud.Factory.file(soundpath)
    
    # Successfully return.
    return


## Documentation for a function.
#
# More details.
def stealth_start():
    global bot
    global armature
    
    # Determine if we are allowed to conceal ourselves.
    if bot.get("prv_Stealth") == False:
        # We are allowed.  Begin concealing ourselves.
        bot["prv_Stealth"] = True # Update that we are concealed.
        armature.playAction("stealth_start", 1, 31, 0, 0, 0,  bge.logic.KX_ACTION_MODE_PLAY, 0.0, 0, bot.get("pub_DeployRate"))

    # Successfully return.
    return


## Documentation for a function.
#
# More details.
def stealth_end():
    global bot
    global armature
    
    # Determine if we are allowed to reveal ourselves.
    if bot.get("prv_Stealth") == True:
        # We are allowed.  Begin revealing ourselves.
        stealth = False
        bot["prv_Stealth"] = False # Update that we are revealed.
        armature.playAction("stealth_end", 1, 31, 0, 0, 0,  bge.logic.KX_ACTION_MODE_PLAY, 0.0, 0, bot.get("pub_DeployRate"))

    # Successfully return.
    return


## Documentation for a function.
#
# More details.
def fire_primary_1():
    global bot
    global scene
    
    # Determine if we are allowed to fire.
    if bot.get("prv_Stealth") == True:
        bot["prv_Counter"] = 0; # Reset the fire rate counter.
        return # We are not allowed to fire.

    # Increment the fire rate counter and check if we are allowed to fire.
    bot["prv_Counter"] = bot["prv_Counter"] + 1
    if (bot["prv_Counter"] < 10):
        return # We are not allowed to fire.
    
    # Fire the primary weapon, right cannon.
    if ( bot.get("pub_ProjectileAlternate") == False or \
         bot.get("prv_ProjectileToggle") == False ):
        bullet = scene.addObject(bot.get("pub_ProjectileObject"), "Sentry2_BulletSpawnR", 150)
        bullet.applyForce((0, 0, -bot.get("pub_ProjectileRate")), True)
        bullet.color = (1,0,0,1)
    
    # Fire the primary weapon, left cannon.
    if ( bot.get("pub_ProjectileAlternate") == False or \
         bot.get("prv_ProjectileToggle") == True ):
        bullet = scene.addObject(bot.get("pub_ProjectileObject"), "Sentry2_BulletSpawnL", 150)
        bullet.applyForce((0, 0, -bot.get("pub_ProjectileRate")), True)
        bullet.color = (1,0,0,1)

    # Update the projectile left-right toggle.
    bot["prv_ProjectileToggle"] = not bot.get("prv_ProjectileToggle")
    
    # Play sound.
    bge.logic.device.play(bot["snd_fire_primary_1"])

    # Finally, reset the fire counter.
    bot["prv_Counter"] = 0

    # Successfully return.
    return


## Documentation for a function.
#
# More details.
def check_target():
    global bot
    global scene

    # Determine the the delta vector from the players current
    # position to the bots current position.
    delta = scene.objects["Player"].position - bot.position
    # print(delta.length)
    
    # Return the length scalar.
    return delta.length
    

## Documentation for a function.
#
# More details.
def update():

    # Grab the keyboard input.
    keyboard = bge.logic.keyboard

    # TODO: comment
    distance = check_target()

    # TODO: comment
    if (distance > 60):
#        bot["prv_Counter"] = 0 # Clear weapon counter.
        return
    print(bot["prv_Counter"])

    # Start Stealth.
    #if bge.logic.KX_INPUT_ACTIVE == keyboard.events[bge.events.GKEY]:
    if ( bot.get("prv_Stealth") == False and \
         distance > 50 ):
        stealth_start()

    # End Stealth.
    # if bge.logic.KX_INPUT_ACTIVE == keyboard.events[bge.events.TKEY]:
    if ( bot.get("prv_Stealth") == True and \
         distance < 40 ):
        stealth_end()

    # Fire Primary 1.
#    if bge.logic.KX_INPUT_JUST_ACTIVATED == keyboard.events[bge.events.SPACEKEY]:
    if (distance < 30 ):
        fire_primary_1()

    # Successfully return.
    return


## Documentation for a function.
#
# Main program execution starts here.  This method fully processes the bots
# behavior as needed.
initialize()
update()
